package ai;

import java.util.List;

public class MiniMax {
    
    private static final int MAX_LEVEL = 10;

    private Problem problem;
    private byte maxPlayer;

    public MiniMax(Problem problem, byte maxPlayer) {
        this.problem = problem;
        this.maxPlayer = maxPlayer;
    }

    public float maxValue(Node node, float alpha, float beta) {
        float utilityValue = node.getState().getUtilityValue(maxPlayer);
        if (utilityValue != 0) { //if 0, then it's a leaf node
            node.setUtilityValue(utilityValue);
            return node.getUtilityValue();
        }
        if (node.getLevel() >= MAX_LEVEL) {
            node.setUtilityValue(node.getState().heuristicValue(maxPlayer));
            return node.getUtilityValue();
        }
        List<State> children = node.getState().getChildren();
        for (State childrenState : children) {
            float minValue = minValue(new Node(node.getLevel()+1, childrenState), alpha, beta);
            if (minValue > alpha) {
                alpha = minValue;
            }
            if (alpha >= beta) {
                return beta;
            }
        }
        return alpha;
    }
    
    public float minValue(Node node, float alpha, float beta) {
        float utilityValue = node.getState().getUtilityValue(maxPlayer);
        if (utilityValue != 0) { //if 0, then it's a leaf node
            node.setUtilityValue(utilityValue);
            return node.getUtilityValue();
        }
        if (node.getLevel() >= MAX_LEVEL) {
            node.setUtilityValue(node.getState().heuristicValue(maxPlayer));
            return node.getUtilityValue();
        }
        List<State> children = node.getState().getChildren();
        for (State childrenState : children) {
            float maxValue = maxValue(new Node(node.getLevel()+1, childrenState), alpha, beta);
            if (maxValue < beta) {
                beta = maxValue;
            }
            if (beta <= alpha) {
                return alpha;
            }
        }
        return beta;
    }
}
